/*****************************************************************************
 * csri: common subtitle renderer interface
 *****************************************************************************
 * Copyright (C) 2007  David Lamparter
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  - The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
 ****************************************************************************/

/** \file csri.h - main CSRI (common subtitle renderer interface) include.
 * $Id: csri.h 45 2007-06-20 01:00:40Z equinox $ */

#ifndef _CSRI_H
/** \cond */
#define _CSRI_H 20070119
/** \endcond */

#include <stddef.h>			/* ptrdiff_t */

#ifdef __cplusplus
extern "C" {
#endif

#ifndef CSRIAPI
    /** CSRI API attributes.
     * defaults to \c extern.
     */
#define CSRIAPI extern
#endif

    /** \defgroup base CSRI base API. */
    /*@{*/

    /** pixel format specification for frames */
    enum csri_pixfmt {
        CSRI_F_RGBA = 0,
        CSRI_F_ARGB,
        CSRI_F_BGRA,
        CSRI_F_ABGR,

        CSRI_F_RGB_ = 0x100,
        CSRI_F__RGB,
        CSRI_F_BGR_,			/**< Windows "RGB32" */
        CSRI_F__BGR,

        CSRI_F_RGB  = 0x200,
        CSRI_F_BGR,			/**< Windows "RGB24" */

        CSRI_F_AYUV = 0x1000,
        CSRI_F_YUVA,
        CSRI_F_YVUA,

        CSRI_F_YUY2 = 0x1100,

        CSRI_F_YV12A = 0x2011,		/**< planar YUV 2x2 + alpha plane */
        CSRI_F_YV12 = 0x2111		/**< planar YUV 2x2 */
                  };

#define csri_is_rgb(x) ((x) < 0x1000)
#define csri_is_yuv(x) ((x) >= 0x1000)
#define csri_is_yuv_planar(x) ((x) >= 0x2000)
#define csri_get_yuv_planar_xred(x) (0xf & (x))
#define csri_get_yuv_planar_yred(x) (0xf & ((x) >> 4))
#define csri_is_yuv_packed(x) ((x) >= 0x1000 && (x) < 0x2000)
#define csri_has_alpha(x) (((x) & 0xfff) < 0x100)

    /** frame/image format specification pre-fed to the renderer */
    struct csri_fmt
    {
        /** format to be used */
        enum csri_pixfmt pixfmt;
        /** image width, full frame.
         *
         * This should specify the full size of the frame.
         * Specifying the video sub-size (in case of added black
         * borders) is left to an extension.
         */
        unsigned width;
        /** image height */
        unsigned height;
    };

    /** single frame to be fed to the renderer. */
    struct csri_frame
    {
        /** frame format.
         * It is an application bug if this differs from the one
         * passed in struct #csri_fmt to csri_query_fmt()
         */
        enum csri_pixfmt pixfmt;
        /** the frame's data.
         * Packed formats only use planes[0]; planar formats
         * have the data ordered as Y, U, V[, A].
         *
         * Also note that the topmost line always comes first.
         * The Windows biHeight strange-ity is \a NOT duplicated.
         */
        unsigned char *planes[4];
        /** strides for the individual planes.
         * Stride means full byte offset, i.e. do \a not add
         * frame width
         */
        ptrdiff_t strides[4];
    };

#ifndef CSRI_OWN_HANDLES
    /** opaque renderer data */
    typedef void csri_rend;
    /** opaque instance data */
    typedef void csri_inst;
#endif

#ifdef DOXYGEN
    /** disable the emission of the csri_rend and csri_inst typedefs.
     * define this if you are in a renderer and are typedef'ing
     * csri_rend and csri_inst to your own structs.
     */
#define CSRI_OWN_HANDLES
#endif

    /** renderer description.
     * \ingroup loader
     */
    struct csri_info
    {
        /** an identifier for the renderer.
         * - MUST match the regular expression
         *   \code ^[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])? \endcode
         *   i.e. consists only of letters, numbers and underscores;
         *   must start with a letter and doesnt have an underscore
         *   as the last character.
         */
        const char *name;
        /** an identifier to the exact version of the renderer.
         * most likely a version number or revision identifier.
         *
         * The helper library does a strcmp over this field in order
         * to order multiple instances of the same renderer. Use
         * higher-byte-value strings for newer renderers.
         */
        const char *specific;

        /** a nice name to be presented to the user */
        const char *longname;
        /** the renderer's author */
        const char *author;
        /** a copyright string. Copyright (c) 2042 by Mr. Nice Guy */
        const char *copyright;
    };

    /** data of extension-dependent type.
     * The field to be used MUST be specified in the extension where it is used.
     */
    union csri_vardata
    {
        long lval;
        double dval;
        const char *utf8val;
        void *otherval;
    };

    /** extension identifier.
     * This follows reverse DNS syntax, i.e.:
     * \code root.branch.leaf \endcode
     * you can either reverse a registered domain name, e.g.
     * \code com.microsoft.csri.usegdiplus \endcode
     * or ask the CSRI maintainers to assign a namespace to you.
     *
     * currently registered namespaces are:
     *
     * \code
     * csri.* - official extensions
     * asa.*  - custom extensions of the asa renderer
     * \endcode
     */
    typedef const char *csri_ext_id;

    /** script loading parameters.
     * each flag MUST have an associated extension, which can be queried
     * with csri_query_ext(). If the open flag constitutes an extension on its
     * sole own, csri_query_ext() can return a meaningless non-NULL value for
     * it.
     *
     * The data field used must be specified.
     *
     * An extension can have multiple flags. In that case, the flags should have
     * the extension name as common prefix, separated with a dot.
     *
     * A renderer MUST ignore unknown open flags. It MUST NOT return an error
     * just because it does not support a particular flag.
     */
    struct csri_openflag
    {
        /** flag name */
        csri_ext_id name;
        /** flag data argument */
        union csri_vardata data;
        /** link to next flag */
        struct csri_openflag *next;
    };

    /** load a script from a file.
     * \param renderer the handle to the renderer
     * \param filename the path to the file to be loaded. \n
     *   The filename should be encoded as UTF-8. Windows renderers are
     *   expected to convert it to UTF-16 and use the Unicode Windows API
     *   functions.
     * \param flags a linked list of open flags. \n
     *   The caller manages memory allocation, i.e. static allocation is OK.
     * \return the renderer instance handle, or NULL on error.
     */
    CSRIAPI csri_inst *csri_open_file(csri_rend *renderer,
                                      const char *filename, struct csri_openflag *flags);

    /** load a script from memory.
     * \param renderer the handle to the renderer
     * \param data pointer to the first data byte. \n
     *   The caller manages memory allocation and should free the data after
     *   calling csri_open_mem(). If the renderer needs to keep the data, it
     *   must copy it. \n
     *   The renderer is not allowed to write to the data.
     * \param length length, in bytes, of the data
     * \param flags see csri_open_file()
     * \return the render instance handle, or NULL on error.
     */

    CSRIAPI csri_inst *csri_open_mem(csri_rend *renderer,
                                     const void *data, size_t length, struct csri_openflag *flags);

    /** close a renderer instance.
     * \param inst the instance handle.
     */
    CSRIAPI void csri_close(csri_inst *inst);


    /** query / set the image format and size.
     * \param inst the renderer instance handle
     * \param fmt the format and image size to be used
     * \return 0 if the format was successfully set,
     *   any other value in case of error.
     */
    CSRIAPI int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt);

    /** render a single frame
     * \param inst the renderer instance handle
     * \param frame frame data to render to
     * \param time associated timestamp of the frame
     */
    CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame,
                             double time);


    /** query for an extension.
     * \param rend the renderer handle
     * \param extname the extension's identifier
     * \return NULL if the extension is not supported,
     *   a pointer to extension-specific data otherwise
     *
     * The data pointed to by the return value does not neccessarily need to
     * have any meaning; An extension that does not need to return data
     * can return a pointer to whatever it wants, as long as that pointer is
     * not NULL.
     *
     * In the usual case, the pointer is supposed to point to a struct with
     * function pointers and other information as needed.
     */
    CSRIAPI void *csri_query_ext(csri_rend *rend, csri_ext_id extname);

    /*@}*/

    /** \defgroup loader CSRI loader API.
     *
     * These functions locate renderers based on given parameters.
     *
     * <b>Renderers must implement these functions as well.</b>
     *
     * They are used by the library to grab renderer information
     * from a shared object; and also this way a single renderer
     * can be linked directly into an appliaction.
     */
    /*@{*/

    /** get renderer information
     * \param rend the renderer handle
     * \return information about the renderer, or NULL in case the renderer
     *   encountered an internal error.
     */
    CSRIAPI struct csri_info *csri_renderer_info(csri_rend *rend);

    /** try to load a given renderer
     * \param name the name of the renderer, as in csri_info.name
     * \param specific the specific version of the renderer,
     *   as in csri_info.specific;\n
     *   alternatively NULL if any version of the renderer is ok.
     * \return a handle to the renderer if it was successfully loaded,
     *   NULL otherwise.
     */
    CSRIAPI csri_rend *csri_renderer_byname(const char *name,
                                            const char *specific);

    /** try to find an implementation of the given extensions.
     * \param next number of extensions pointed to by ext
     * \param ext array of extensions to search for
     * \return a handle to a renderer supporting ALL of the
     *   extensions, NULL if none was found.
     */
    CSRIAPI csri_rend *csri_renderer_byext(unsigned n_ext, csri_ext_id *ext);

    /** get the default (highest priority) renderer
     * \return a handle to the default renderer, or NULL if
     *   no renderer is installed.
     *
     * Together with csri_renderer_next(), this can be used
     * to enumerate all installed renderers.
     */
    CSRIAPI csri_rend *csri_renderer_default();

    /** get the next lower priority renderer
     * \param prev the current renderer
     * \return the renderer with the next lower priority than
     *   the one named in prev, or NULL if prev is the last
     *   renderer installed.
     */
    CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev);

    /*@}*/

#ifdef __cplusplus
}
#endif

#endif /* _CSRI_H */
